/*
   (C) 2007 - Michael Ocean - Boston University

  This work is a part of the larger snBench project.  Information
  can be found at: http://csr.bu.edu/snbench

  This program is free software; you can redistribute it and/or
  modify it under the terms of Version 2 of the GNU General Public 
  License.
  
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.
  
  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package sxe.sensors;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.StringTokenizer;
import snobject.snLong;
import snobject.snString;
import snobject.snStruct;
import sxe.sensors.KismetClient.msgtypes;

public class KismetMessage {
	protected long time;
	protected long seqno;
	protected msgtypes type;
	protected String sensorsource;
	protected String originalMessage;
	protected Hashtable<String,String> parms;
	
	public Enumeration<String> getKeys(){
		return parms.keys();
	}
	
	public String getValue(String field){
		return parms.get(field);
	}
	
	public void setSeqNo(long n){
		seqno = n;
	}
	public long getSeqNo(){
		return seqno;
	}
	
	public String getString(){
		return "[" + time + "]" + "{" + type + "}:" + originalMessage; 
	}
	
	/**
	 * @return an snStruct of the KismetMessage
	 */
	public snStruct getSnObject(){
		long l = (long)getTime();
		snStruct snstruct = new snStruct();
		snstruct.put("MSG_TYPE", getType().toString());
		snstruct.put(new snString("MSG_TIME"), new snLong(l));
		snstruct.put(new snString("MSG_RECV"), new snString(snbenchlib.Util.formatTime(l)));
		snstruct.put(new snString("MSG_SENSOR"), new snString(sensorsource));
		snstruct.put("MSG_ORIG", getOriginalMessage());
		if(getParms()!=null)
			snstruct.putAll(getParms());
		
		return(snstruct);
	}
	
	/**
	 * Takes a KismetMessage and parses to populate object.
	 * Records time as local time when parsing occurs, msgtype
	 * from Kismet protocol prefix and builds a params HT by
	 * parsing the message.  string value preserves the original
	 * messgae for debugging, etc.
	 * 
	 * @param s the Kismet message to be parsed.
	 */
	public KismetMessage(String s, String sensorName){
		//time = System.nanoTime();
		time = System.currentTimeMillis();
		sensorsource = sensorName;
		originalMessage = s;
		type = msgtypes.parse(s.substring(1,s.indexOf(":")));
		parseKismetProtoFields(msgtypes.getFieldsForMsgType(type),s);
	}
	
	private void parseKismetProtoFields(String sFields,String sValues){
		String sVal = null;
		String sCont = null;
		String sField = null;
		
		if(sFields.equals(""))
			return;
		
		parms = new Hashtable<String, String>();
		StringTokenizer sf = new StringTokenizer(sFields,",");
		StringTokenizer sv = new StringTokenizer(sValues.substring(sValues.indexOf(":")+1)," ");
		int i=0;
		
		//System.err.println("fields=" + sf.countTokens() + ", vals=" + sv.countTokens());
		while(sv.hasMoreElements()){
			sField = sf.nextToken();
			//System.err.println("field(" + i + ")=" + sField);
			
			sVal = sv.nextToken();
			//System.err.print("val(" + i + ")=" + sVal);
			if(sVal.startsWith(String.valueOf('\01'))){
				if(sVal.charAt(sVal.length()-1)!='\01'){
					do{
						sCont = sv.nextToken();
						sVal.concat(sCont);
						//System.err.print("+" + sCont);
					}while(!sCont.contains(String.valueOf('\01')));
				}
			}
			//System.err.println();
			parms.put(sField, sVal);
			i++;
		}
	}

	public Hashtable<String, String> getParms() {
		return parms;
	}

	public long getTime() {
		return time;
	}

	public msgtypes getType() {
		return type;
	}

	public String getOriginalMessage() {
		return originalMessage;
	}
}